// 参考资料
// https://www.jianshu.com/p/13dca2711b6e
// https://juejin.cn/post/6844903737161433102

import wangEditor from "wangeditor";

const { BtnMenu } = wangEditor;
// 第一，菜单 class ，Button 菜单继承 BtnMenu class
class FormatBrushMenu extends BtnMenu {
    constructor(editor) {
        // data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
        // 图表直接用的element-ui的图标，请自行调整
        const $elem = wangEditor.$(
            `<div class="w-e-menu el-icon-s-open" data-title="格式刷">
            </div>`
        );
        super($elem, editor);
        const me = this;
        me.editor = editor;
        // 监听编辑器鼠标释放事件
        editor.$textElem.on("mouseup", () => {
            // 如果格式刷功能出于激活状态
            if (me._active) {
                // 延迟执行,避免获取不到正确的元素
                setTimeout(() => {
                    // 复制格式刷样式
                    pasteStyle(editor);
                    // 取消格式刷激活样式
                    me.unActive();
                }, 100);
            }
        });
    }
    // 菜单点击事件
    clickHandler() {
        const me = this;
        const editor = me.editor;
        if (me._active) {
            // 已经在激活状态时取消激活
            me.unActive();
            // 清空格式刷样式数据
            editor.copyStyleList = []
        } else {
            // 没有选中则终端
            if (editor.selection.isSelectionEmpty()) return;
            // 激活按钮
            me.active();
            // 获取格式刷样式
            const domToParse =
                editor.selection.getSelectionContainerElem().elems[0];
            const copyStyleList = parseDom(domToParse);
            // 保存格式刷样式
            editor.copyStyleList = copyStyleList;
        }
    }
    tryChangeActive() { }
}

// 菜单 key ，各个菜单不能重复
const menuKey = "formatBrush";

// 注册菜单
wangEditor.registerMenu(menuKey, FormatBrushMenu);

// 复制选中dom的样式
function parseDom(dom) {
    let targetDom = null;
    const nodeArray = [];

    getTargetDom(dom);

    getAllStyle(targetDom);

    function getTargetDom(dom) {
        for (const i of dom.childNodes) {
            if (i.nodeType === 3 && i.nodeValue && i.nodeValue.trim() !== "") {
                targetDom = dom;
                return;
            }
        }
        getTargetDom(dom.children[0]);
    }

    function getAllStyle(dom) {
        if (!dom) return;
        const tagName = dom.tagName.toLowerCase();
        if (tagName === "p") {
            nodeArray.push({
                tagName: "span",
                attributes: Array.from(dom.attributes).map((i) => {
                    return {
                        name: i.name,
                        value: i.value
                    };
                })
            });
            return;
        } else {
            nodeArray.push({
                tagName: tagName,
                attributes: Array.from(dom.attributes).map((i) => {
                    return {
                        name: i.name,
                        value: i.value
                    };
                })
            });
            getAllStyle(dom.parentNode);
        }
    }
    return nodeArray;
}

function addStyle(text, nodeArray) {
    let currentNode = null;
    nodeArray.forEach((ele, index) => {
        const node = document.createElement(ele.tagName);
        for (const attr of ele.attributes) {
            node.setAttribute(attr.name, attr.value);
        }
        if (index === 0) {
            node.innerText = text;
            currentNode = node;
        } else {
            node.appendChild(currentNode);
            currentNode = node;
        }
    });
    return currentNode;
}

// 粘贴
function pasteStyle(editor) {
    // 获取格式刷保存的样式
    const copyStyleList = editor.copyStyleList;
    // 有样式说明格式刷被激活
    if (copyStyleList) {
        // 获取当前选中内容
        // 如果没选中也会执行，再次使用需要重新激活格式刷功能
        const text = editor.selection.getSelectionText();
        const targetDom = addStyle(text, copyStyleList);
        editor.cmd.do("insertHTML", targetDom.outerHTML);
        // 清空格式刷样式
        editor.copyStyleList = null;
    }
}
